package com.foreveross.bsl.mongodb.repository.handler;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.springframework.dao.DataAccessException;
import org.springframework.data.authentication.UserCredentials;
import org.springframework.data.mongodb.core.MongoDbUtils;
import org.springframework.util.Assert;

import com.foreveross.bsl.mongodb.repository.router.RouterMongodbFactory;
import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBObject;
import com.mongodb.Mongo;
import com.mongodb.WriteConcern;

public class SimpleRouterScheme implements RouterScheme {

	private UserCredentials credentials;
	private WriteConcern writeConcern;
	private DB db;

	private String routerDatabase = "router_database"; //router database
	private String routerConnection = "router_connection"; //router connection 
	private String globalDatabasePackage;
	
	private RouterMongodbFactory routerMongodbFactory;
	
	/**
	 * @param credentials
	 * @param routerMongodbFactory
	 */
	public SimpleRouterScheme(UserCredentials credentials,
			RouterMongodbFactory routerMongodbFactory) {
		this.credentials = credentials;
		this.routerMongodbFactory = routerMongodbFactory;
	}

	/*
	 * (non-Javadoc)
	 * @see org.springframework.data.mongodb.MongoDbFactory#getDb(java.lang.String)
	 */
	@Override
	public DB getDb(String registerNo, Class clazz) throws DataAccessException {
		String dataBaseName = "";
		if(matcheGlobal(clazz.getPackage())){
			dataBaseName = routerMongodbFactory.getDefaultDatabaseName();
		} else {
			DBObject obj = getDatabaseDBObject(registerNo);
			if(obj != null){
				dataBaseName = (String)obj.get("database_name");
			} else {
				dataBaseName = routerMongodbFactory.getDefaultDatabaseName();
			}
		}

		Mongo curMongo = routerMongodbFactory.getMongo();
		DB db = MongoDbUtils.getDB(curMongo, dataBaseName, credentials);
		
		if (writeConcern != null) {
			db.setWriteConcern(writeConcern);
		}

		return db;
	}
	
	/**
	 * routerDatabase collection keys:id,registerNo,databaseName
	 * @param key
	 * @return
	 */
	private <T> DBObject getDatabaseDBObject(String key){
		db = MongoDbUtils.getDB(routerMongodbFactory.getMongo(), routerMongodbFactory.getDefaultDatabaseName(), credentials);
		
		if(db.collectionExists(routerDatabase)){
			DBCollection coll = db.getCollection(routerDatabase);
			BasicDBObject obj = new BasicDBObject("register_no",key);
			return coll.findOne(obj);
		} else {
			throw new RuntimeException("routerDatabase is not exist!S");
		}
	}

	/* (non-Javadoc)
	 * @see com.foreveross.common.repository.mongodb.handler.RouterScheme#getDb(java.lang.String, java.lang.Class, java.lang.String)
	 */
	@Override
	public DB getDb(String registerNo, Class clazz, String dbName)
			throws DataAccessException {
		Mongo curMongo = routerMongodbFactory.getMongo();
		DB db = MongoDbUtils.getDB(curMongo, dbName, credentials);

		if (writeConcern != null) {
			db.setWriteConcern(writeConcern);
		}

		return db;
	}
	
	private boolean matcheGlobal(Package p){
		Assert.notNull(p, "Package must be not null");
		if(globalDatabasePackage != null){
			String[] packages = globalDatabasePackage.split(",");
			for (int i = 0; i < packages.length; i++) {
				String packageName = p.getName();
				Pattern pattern = Pattern.compile(packages[i]);
				Matcher matcher = pattern.matcher(packageName);
				if(matcher.matches()){
					return true;
				} 
			}
		}
		return false;
	}

	/**
	 * @return the globalDatabasePackage
	 */
	public String getGlobalDatabasePackage() {
		return globalDatabasePackage;
	}

	/**
	 * @param globalDatabasePackage the globalDatabasePackage to set
	 */
	public void setGlobalDatabasePackage(String globalDatabasePackage) {
		this.globalDatabasePackage = globalDatabasePackage;
	}
	
}
